package org.cloudbus.cloudsim.examples;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;

import org.cloudbus.cloudsim.Cloudlet;
import org.cloudbus.cloudsim.CloudletSchedulerSpaceShared;
import org.cloudbus.cloudsim.CloudletSchedulerTimeShared;
import org.cloudbus.cloudsim.Datacenter;
import org.cloudbus.cloudsim.DatacenterBroker;
import org.cloudbus.cloudsim.DatacenterCharacteristics;
import org.cloudbus.cloudsim.Host;
import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.Pe;
import org.cloudbus.cloudsim.Storage;
import org.cloudbus.cloudsim.UtilizationModel;
import org.cloudbus.cloudsim.UtilizationModelFull;
import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.VmAllocationPolicySimple;
import org.cloudbus.cloudsim.VmSchedulerTimeShared;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.provisioners.BwProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.RamProvisionerSimple;
/**
 * Title: Cloudsim toolkit
 * Description: simulation example how to create datacenter
 * 
 * 
 * */

public class CloudSimExample9
{
	private static List<Cloudlet> cloudLetList;
	private static List<Vm> vmList;
	
	public static void main(String [] args)
	{
		Log.printLine("Starting CloudSimExample 9....");
		try
		{
			int number_user=1;
			Calendar calendar=Calendar.getInstance();
			boolean trace_flag=false;
			CloudSim.init(number_user, calendar, trace_flag);
			Datacenter datacenter0= createDataCenter("datacenter0");
			//Datacenter datacenter1=createDataCenter("datacenter1");
			DatacenterBroker broker1= createDataBroker("broker1");
			int brokerId1=broker1.getId();
			vmList= new ArrayList<Vm>();
			int vmid = 0;
			int mips = 1000;
			long size = 10000; // image size (MB)
			int ram = 100; // vm memory (MB)
			long bw = 1000;
			int pesNumber = 2; // number of cpus
			String vmm = "Xen"; // VMM name
			Vm vm1=new Vm(vmid, brokerId1, mips,pesNumber, ram, bw, size, vmm, new CloudletSchedulerSpaceShared());
			vmList.add(vm1);
			broker1.submitVmList(vmList);
			cloudLetList=new ArrayList<Cloudlet>();
			int id = 0;
			long length = 40000;
			long fileSize = 300;
			long outputSize = 300;
			UtilizationModel utilizationModel=new UtilizationModelFull();
			int cloudletPesNumber=3;
			Cloudlet cloudlet1=new Cloudlet(id, length, cloudletPesNumber, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
			Cloudlet cloudlet2=new Cloudlet(1, length, cloudletPesNumber, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
			cloudlet1.setUserId(brokerId1);
			cloudlet1.setVmId(vmid);
			cloudLetList.add(cloudlet1);
			cloudlet2.setUserId(brokerId1);
			cloudlet2.setVmId(vmid);
			cloudLetList.add(cloudlet2);
			broker1.submitCloudletList(cloudLetList);
			CloudSim.startSimulation();
			CloudSim.stopSimulation();
			List<Cloudlet> newList=broker1.getCloudletReceivedList();
			printCloudletList(newList);
			Log.printLine("CloudSimExample9 finish" );
		}
		catch(Exception e)
		{
			e.printStackTrace();
			Log.printLine("Here i am");
			Log.print("Unwanted errors happen");
		}
	}
	private static void printCloudletList(List<Cloudlet> list) {
		int size = list.size();
		Cloudlet cloudlet;

		String indent = "    ";
		Log.printLine();
		Log.printLine("========== OUTPUT ==========");
		Log.printLine("Cloudlet ID" + indent + "STATUS" + indent
				+ "Data center ID" + indent + "VM ID" + indent + "Time" + indent
				+ "Start Time" + indent + "Finish Time");

		DecimalFormat dft = new DecimalFormat("###.##");
		for (int i = 0; i < size; i++) {
			cloudlet = list.get(i);
			Log.print(indent + cloudlet.getCloudletId() + indent + indent);

			if (cloudlet.getCloudletStatus() == Cloudlet.SUCCESS) {
				Log.print("SUCCESS");

				Log.printLine(indent + indent + cloudlet.getResourceId()
						+ indent + indent + indent + cloudlet.getVmId()
						+ indent + indent
						+ dft.format(cloudlet.getActualCPUTime()) + indent
						+ indent + dft.format(cloudlet.getExecStartTime())
						+ indent + indent
						+ dft.format(cloudlet.getFinishTime()));
			}
		}
	}


	
	public static DatacenterBroker createDataBroker(String name)
	{
		DatacenterBroker broker=null;
		try{
			broker=new DatacenterBroker(name);
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}
		return broker;
	}
	public static Datacenter createDataCenter(String name)
	{
		// Here are the steps needed to create a PowerDatacenter:
				// 1. We need to create a list to store
				// our machine
				List<Host> hostList = new ArrayList<Host>();

				// 2. A Machine contains one or more PEs or CPUs/Cores.
				List<Pe> peList = new ArrayList<Pe>();
				int mips = 1000;

				// 3. Create PEs and add these into a list.
				peList.add(new Pe(0, new PeProvisionerSimple(mips))); // need to store Pe id and MIPS Rating
				peList.add(new Pe(1, new PeProvisionerSimple(mips)));
				// 4. Create Host with its id and list of PEs and add them to the list
				// of machines
				int hostId = 0;
				int ram = 2048; // host memory (MB)
				long storage = 1000000; // host storage
				int bw = 10000;

				hostList.add(
					new Host(
						hostId,
						new RamProvisionerSimple(ram),
						new BwProvisionerSimple(bw),
						storage,
						peList,
						new VmSchedulerTimeShared(peList)
					)
				); // This is our machine

				// 5. Create a DatacenterCharacteristics object that stores the
				// properties of a data center: architecture, OS, list of
				// Machines, allocation policy: time- or space-shared, time zone
				// and its price (G$/Pe time unit).
				String arch = "x86"; // system architecture
				String os = "Linux"; // operating system
				String vmm = "Xen";
				double time_zone = 10.0; // time zone this resource located
				double cost = 3.0; // the cost of using processing in this resource
				double costPerMem = 0.05; // the cost of using memory in this resource
				double costPerStorage = 0.001; // the cost of using storage in this
												// resource
				double costPerBw = 0.0; // the cost of using bw in this resource
				LinkedList<Storage> storageList = new LinkedList<Storage>(); // we are not adding SAN
															// devices by now

				DatacenterCharacteristics characteristics = new DatacenterCharacteristics(
						arch, os, vmm, hostList, time_zone, cost, costPerMem,
						costPerStorage, costPerBw);

				// 6. Finally, we need to create a PowerDatacenter object.
				Datacenter datacenter = null;
				try {
					datacenter = new Datacenter(name, characteristics, new VmAllocationPolicySimple(hostList), storageList, 0);
				} catch (Exception e) {
					e.printStackTrace();
				}

				return datacenter;
		
		
	}
}